home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 2.toast / pc / sample code / human interface toolbox / modeless dialog sample / application.c next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  9.8 KB  |  401 lines

  1. /*
  2.     File:        Application.c
  3.  
  4.     Contains:    a sample application showing how to implement a 
  5.                 modeless dialog with a couple of controls.
  6.  
  7.     Written by: Nitin Ganatra    
  8.  
  9.     Copyright:    Copyright © 1994-1999 by Apple Computer, Inc., All Rights Reserved.
  10.  
  11.                 You may incorporate this Apple sample source code into your program(s) without
  12.                 restriction. This Apple sample source code has been provided "AS IS" and the
  13.                 responsibility for its operation is yours. You are not permitted to redistribute
  14.                 this Apple sample source code as "Apple sample source code" after having made
  15.                 changes. If you're going to re-distribute the source, we require that you make
  16.                 it clear in the source that the code was descended from Apple sample source
  17.                 code, but that you've made changes.
  18.  
  19.     Change History (most recent first):
  20.                 8/9/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  21.                 
  22.  
  23. */
  24. #include <Resources.h>
  25. #include <Dialogs.h>
  26. #include <Menus.h>
  27. #include "SampleHeader.h"
  28.  
  29. /* Two globals.  One always tells me whether I'm in the background or not    */
  30. /* (maintained in the Suspend/Resume event handler in MainEventLoop()), and    */
  31. /* another that allows me to cleanly drop out of my main event loop from     */
  32. /* anywhere.  Sure ExitToShell() works, too, but I like to exit in only one    */
  33. /* way, and this global allows me to do that.                                */
  34. Boolean gDone;
  35. Boolean gInBackground;
  36.  
  37. /*-------------------------------------------------------------------------------------*/
  38.  
  39. void main()
  40. {
  41.     InitApplication();
  42.     PreEventLoop();
  43.     MainEventLoop();
  44. }
  45.  
  46.  
  47. /*-------------------------------------------------------------------------------------*/
  48. /*
  49.     InitApplication - initializes the toolbox, my globals, and my menu bar.
  50. */
  51. void InitApplication()
  52. {
  53.     Handle theMenu;
  54.  
  55.     // Toolbox initialization
  56.     MaxApplZone();
  57.     InitGraf(&qd.thePort);
  58.     InitFonts();
  59.     InitWindows();
  60.     InitMenus();
  61.     TEInit();
  62.     InitDialogs(nil);
  63.     InitCursor();
  64.     FlushEvents(0,everyEvent);
  65.     
  66.     // Application initialization
  67.     gDone = false;
  68.     gInBackground = false;
  69.     
  70.     theMenu = GetNewMBar(kMenuBarResID);
  71.     if ( theMenu != nil )
  72.     {
  73.         SetMenuBar(theMenu);
  74.         AppendResMenu(GetMenuHandle(kAppleMenu), 'DRVR');
  75.         DrawMenuBar();
  76.     }
  77.     else
  78.         /* If the menu stuff failed, something just ain't    */
  79.         /* right (most likely some resources are missing).    */
  80.         gDone = true;
  81.  
  82. }
  83.  
  84.  
  85. /*-------------------------------------------------------------------------------------*/
  86. /*
  87.     DoAboutBox - I just have an Alert dialog box set up in my resources for this.
  88. */
  89. void DoAboutBox()
  90. {
  91.     (void) Alert(kAboutBoxDITLID, nil);
  92. }
  93.  
  94.  
  95. /*-------------------------------------------------------------------------------------*/
  96. /*
  97.     MainEventLoop - handles all events for this application.  Note that the first
  98.     thing done with an event is to check if it belongs to a dialog, and if so the
  99.     event is passed to DoDialogEvent() which handles all dialog events except
  100.     null events.  To check if it's a dialog event, the IsDialogEvent routine is
  101.     called which checks to see if the frontmost window is a dialog and if the
  102.     event is not an update,  a mousedown or an activate for another window.  Note
  103.     that null events are all passed to DoDialogNullEvent, which is needed to keep
  104.     the editText cursor blinking..
  105.  
  106. */
  107. void MainEventLoop()
  108. {
  109.     EventRecord        theEvent;
  110.     WindowPtr        thisWindow;
  111.     short            clickArea;
  112.     Rect            screenRect;
  113.     long            menuResult;
  114.     char            charCode;
  115.  
  116.     while ( !gDone )
  117.     {
  118.         if ( WaitNextEvent(everyEvent, &theEvent, 0, nil) )
  119.         {
  120.             if ( IsDialogEvent(&theEvent) == true )
  121.             {
  122.                 DoDialogEvent(&theEvent);
  123.                 continue;
  124.             }
  125.  
  126.             switch (theEvent.what)
  127.             {
  128.                 case mouseDown:
  129.                     clickArea = FindWindow(theEvent.where, &thisWindow);
  130.                     
  131.                     switch ( clickArea )
  132.                     {
  133.                         case inDrag:
  134.                             screenRect = (**GetGrayRgn()).rgnBBox;
  135.                             DragWindow(thisWindow, theEvent.where, &screenRect);
  136.                             break;
  137.                         case inContent:
  138.                             if ( thisWindow != FrontWindow() )
  139.                                 SelectWindow(thisWindow);
  140.                             break;
  141.                         case inGoAway:
  142.                             if ( TrackGoAway(thisWindow, theEvent.where) == true )
  143.                             {
  144.                                 if ( ((WindowRecord *)thisWindow)->windowKind == dialogKind )
  145.                                     DisposeDialog(thisWindow);
  146.                                 else
  147.                                     gDone = true;
  148.                             }
  149.                             break;
  150.                         case inMenuBar:
  151.                             AdjustMenus();
  152.                             menuResult = MenuSelect(theEvent.where);
  153.                             if ( (menuResult  >> 16) != 0 )
  154.                                 (void) MenuCommand(menuResult);
  155.                             break;
  156.                     }
  157.  
  158.                     break;
  159.                 case keyDown:
  160.                     charCode = theEvent.message & charCodeMask;
  161.  
  162.                     if ( (theEvent.modifiers & cmdKey) != 0 ) 
  163.                     {    
  164.                         AdjustMenus();
  165.                         menuResult = MenuKey(charCode);
  166.                 
  167.                         if ( (menuResult  >> 16) != 0 )
  168.                             (void) MenuCommand(menuResult);
  169.                             
  170.                     } 
  171.                     break;
  172.                 case updateEvt:
  173.                     thisWindow = (WindowPtr)theEvent.message;    
  174.                     DoUpdate(thisWindow);
  175.                 
  176.                     break;
  177.                 case 15: 
  178.                     /* Make sure the SIZE resource reflects that suspend evts are accepted.*/
  179.                     if ( theEvent.message & 0x01000000 )         /* Suspend or resume? */
  180.                     {
  181.                         if ( theEvent.message & 0x00000001 )/* Is it a resume event? */
  182.                         {
  183.                             gInBackground = false;
  184.                             SetCursor(&qd.arrow);
  185.                         }
  186.                         else                                 /* It's a suspend event */
  187.                             gInBackground = true;
  188.  
  189.                     }
  190.                     break;
  191.             }
  192.         }
  193.         else
  194.             DoDialogNullEvent(&theEvent);
  195.     }
  196. }
  197.  
  198.  
  199.  
  200. /*-------------------------------------------------------------------------------------*/
  201. /*
  202.     MenuCommand - called in response to keydowns in both my dialog event handler and
  203.     the main event loop.  Note that because of AdjustMenus(), the edit keys will only
  204.     be hit if the dialog is the frontmost window, which is what we want.
  205.  
  206. */
  207. Boolean MenuCommand(long whaHappened)
  208. {
  209.     short        menuID, menuItem;
  210.     Boolean     performedEdit = false;
  211.     DialogPtr    theDialog;
  212.     
  213.     menuID = (whaHappened >> 16);
  214.     menuItem = (whaHappened & 0xFFFF);
  215.     
  216.     switch ( menuID )
  217.     {
  218.         case kAppleMenu:
  219.             HiliteMenu(kAppleMenu);
  220.             if ( menuItem == 1)
  221.                 DoAboutBox();
  222.             break;
  223.  
  224.         case kFileMenu:
  225.             HiliteMenu(kFileMenu);
  226.             switch ( menuItem )
  227.             {
  228.                 case kNewItem:
  229.                     CreateModelessDialog();
  230.                     break;
  231.                 case kQuitItem:
  232.                     gDone = true;
  233.                     break;
  234.             }
  235.             break;
  236.         case kEditMenu:
  237.             // This thing should be a dialog, because the menu items are
  238.             // disabled unless a modeless dialog is frontmost.
  239.             theDialog = (DialogPtr)FrontWindow();
  240.             
  241.             if ( theDialog != nil )
  242.             {
  243.                 HiliteMenu(kEditMenu);            
  244.                 switch ( menuItem )
  245.                 {
  246.                     case kCutItem:
  247.                         DoCut(theDialog);
  248.                         performedEdit = true;
  249.                         break;
  250.                     case kCopyItem:
  251.                         DoCopy(theDialog);
  252.                         performedEdit = true;
  253.                         break;
  254.                     case kPasteItem:
  255.                         DoPaste(theDialog);
  256.                         performedEdit = true;
  257.                         break;
  258.                     case kClearItem:
  259.                         DoClear(theDialog);
  260.                         performedEdit = true;
  261.                         break;
  262.                 }
  263.             }
  264.             break;
  265.     }
  266.     HiliteMenu(0);
  267.     return performedEdit;
  268. }
  269.  
  270.  
  271.  
  272.  
  273. /*-------------------------------------------------------------------------------------*/
  274. /*
  275.     DrawIt - I've included a normal window in this application to show the difference
  276.     between handling events for a dialog and a normal window.  This just draws some
  277.     text into the normal window.
  278.  
  279. */
  280. void DrawIt(WindowPtr win)
  281. {
  282.     short         origFont, origSize;
  283.     
  284.     origFont = win->txFont;
  285.     origSize = win->txSize;
  286.     TextFont(kFontIDGeneva);
  287.     TextSize(48);
  288.  
  289.     ForeColor(redColor);
  290.     PaintRect(&(*win).portRect);
  291.     ForeColor(blackColor);
  292.  
  293.     MoveTo(10, win->portRect.bottom - 10);
  294.     DrawString((StringPtr)"\pModeless Sample");
  295.  
  296.     TextFont(origFont);
  297.     TextSize(origSize);
  298. }
  299.  
  300.  
  301. /*-------------------------------------------------------------------------------------*/
  302. /*
  303.     DrawWindowContent - called by DeviceLoop in the main event loop.  In response to 
  304.     update events.
  305.     
  306.     Since I don't do anything different for different depths, grayscale, etc, I just 
  307.     ignore those parameters, but you don't have to.
  308.  
  309. */
  310. pascal void DrawWindowContent(short pixelDepth, short dFlags, GDHandle theDevice, long theWin)
  311. {
  312. #pragma unused (pixelDepth, dFlags, theDevice)
  313.     GrafPtr        savePort;
  314.  
  315.     GetPort(&savePort);
  316.     SetPort((GrafPtr)theWin);
  317.  
  318.     DrawIt((WindowPtr)theWin);
  319.  
  320.     SetPort(savePort);
  321. }
  322.  
  323.  
  324. /*-------------------------------------------------------------------------------------*/
  325. /*
  326.     CreateNewWindow - called in PreEventLoop to create the normal non-dialog window.
  327.  
  328. */
  329. void MyCreateNewWindow(void)
  330. {
  331.     Rect winDimension;
  332.     
  333.     SetRect(&winDimension, 60, 60, 475, 120);
  334.     (void)NewCWindow(0L, &winDimension, (StringPtr)"\pSample", true, noGrowDocProc,
  335.                             (WindowPtr)-1L, true, 0L);
  336. }
  337.  
  338.  
  339.  
  340. /*-------------------------------------------------------------------------------------*/
  341. /*
  342.     DoUpdate - called in the main event loop.
  343.  
  344. */
  345. void DoUpdate(WindowPtr thisWindow)
  346. {
  347.     static DeviceLoopDrawingUPP    procForDeviceLoop = nil;
  348.  
  349.     SetPort(thisWindow);
  350.  
  351.     if ( procForDeviceLoop == nil )
  352.         procForDeviceLoop = NewDeviceLoopDrawingProc(DrawWindowContent);    
  353.     
  354.     BeginUpdate(thisWindow);
  355.     DeviceLoop(thisWindow->visRgn, procForDeviceLoop, (long)thisWindow, singleDevices);
  356.     EndUpdate(thisWindow);
  357. }
  358.  
  359.  
  360. /*-------------------------------------------------------------------------------------*/
  361.  
  362. void PreEventLoop(void)
  363. {
  364.     MyCreateNewWindow();
  365.     CreateModelessDialog();
  366. }
  367.  
  368.  
  369. /*-------------------------------------------------------------------------------------*/
  370.  
  371. void PostEventLoop(void)
  372. {
  373. }
  374.  
  375.  
  376. /*-------------------------------------------------------------------------------------*/
  377. /*
  378.     AdjustMenus - called in whenever command-keys are pressed, or if the menu bar is
  379.     hit with the mouse, so the menus are adjusted only right before they're accessed.
  380. */
  381. void AdjustMenus(void)
  382. {
  383.     MenuHandle    theFuncsMenu = GetMenu(kEditMenu);
  384.     WindowPtr    theWindow = FrontWindow();
  385.     
  386.     if ( ((WindowRecord *)theWindow)->windowKind != dialogKind )
  387.     {
  388.         DisableItem(theFuncsMenu, kCutItem);
  389.         DisableItem(theFuncsMenu, kCopyItem);
  390.         DisableItem(theFuncsMenu, kPasteItem);
  391.         DisableItem(theFuncsMenu, kClearItem);
  392.     }
  393.     else
  394.     {
  395.         EnableItem(theFuncsMenu, kCutItem);
  396.         EnableItem(theFuncsMenu, kCopyItem);
  397.         EnableItem(theFuncsMenu, kPasteItem);
  398.         EnableItem(theFuncsMenu, kClearItem);
  399.     }
  400. }
  401.